pub fn use_generic(){
    max_of_array();
    max_of_array_generic();
    struct_generic();
}

fn max_of_array(){
    fn max(array: &[i32]) -> i32 {
        let mut max_index = 0;
        let mut i = 1;
        while i < array.len() {
            if array[i] > array[max_index] {
                max_index = i;
            }
            i += 1;
        }
        array[max_index]
    }

    let a = [2, 8, 10, 1, 0, -1];
    println!("max = {}", max(&a));
}

fn max_of_array_generic(){
    trait Comparable {
        fn compare(&self, object: &Self) -> i8;  // Self  means current typeof(this)
    }
    fn max<T: Comparable>(array: &[T]) -> &T {
        let mut max_index = 0;
        let mut i = 1;
        while i < array.len() {
            if array[i].compare(&array[max_index]) > 0 {
                max_index = i;
            }
            i += 1;
        }
        &array[max_index]
    }
    impl Comparable for f64 {
        fn compare(&self, object: &f64) -> i8 {
            if &self > &object { 1}
            else if &self == &object { 0}
            else { -1 }
        }
    }
    let a = [2.0, 3.0, 10.0, 100.0, 12.0];
    println!("max = {}", max(&a));
}



struct Point<T> {
    x: T,
    y: T
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
    fn y(&self) -> &T {
        &self.y
    }
}

//impl new method for specialize type(f64)
impl Point<f64> {
    fn get_x(&self) -> f64 {
        self.x
    }
    fn get_y(&self) -> f64 {
        self.y
    }
}
fn struct_generic(){
    let p = Point { x : String::from("hello"), y : String::from("world")};
    println!("p.x = {}, p.y = {}", p.x(), p.y());
    let p = Point { x : 4.0, y : 5.0};
    println!("p.x = {}, p.y = {}; p.get_x() = {}, p.get_y() = {}", p.x(), p.y(), p.get_x(), p.get_y());
}
